package com.huiquan.icd.service;

import com.huiquan.analysis.domain.User;
import com.huiquan.foundation.constant.BusinessContants;
import com.huiquan.foundation.constant.SubmitStatus;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.constant.BaseContants;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.icd.dao.IcdDiseaseCategoryDao;
import com.huiquan.icd.dao.IcdDiseaseDao;
import com.huiquan.icd.dao.IcdDiseaseNameRecordDao;
import com.huiquan.icd.domain.IcdDisease;
import com.huiquan.icd.domain.IcdDiseaseCategory;
import com.huiquan.icd.domain.IcdDiseaseDto;
import com.huiquan.icd.domain.IcdDiseaseNameRecord;
import com.huiquan.synonymy.domain.Synonymy;
import com.huiquan.synonymy.service.SynonymyService;
import com.huiquan.vocab.constant.VocabConstant;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

@Service
public class IcdDiseaseService extends BaseService {

	@Autowired
	private IcdDiseaseDao icdDiseaseDao;
	@Autowired
	private IcdDiseaseNameRecordDao icdDiseaseNameRecordDao;
	@Autowired
	private IcdDiseaseCategoryDao icdDiseaseCategoryDao;
	@Autowired
	private SynonymyService synonymyService;

	public ModelAndView list(Integer start, String nameSearch, String categorySearch, String exactSearchFlag,
			String countPerPageStr) {
		boolean exactFlag = exactSearchFlag != null && exactSearchFlag.equals("1");

		Map<String, Object> param = new HashMap<>();
		if (nameSearch != null && !nameSearch.isEmpty()) {
			param.put("nameSearch", exactFlag ? nameSearch : "%" + nameSearch + "%");
		}
		if (categorySearch != null && !categorySearch.isEmpty()) {
			param.put("categorySearch", exactFlag ? categorySearch : "%" + categorySearch + "%");
		}
		param.put("disable", BaseContants.DISABLE_VALID);
		int totalSize = icdDiseaseDao.retrieveSize(param);

		Map<String, Integer> pageNo;
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			int countPerPage = Integer.parseInt(countPerPageStr);
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "", countPerPage);
			param.put("countPerPage", countPerPage);
		} else {
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "");
		}
		int endPage = pageNo.get("endPage");
		start = pageNo.get("start");
		int startIndex = pageNo.get("startIndex");

		List<IcdDiseaseDto> list = new ArrayList<>();

		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			list = icdDiseaseDao.retrieveDtoList(param);
		}

		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("nameSearch", "疾病名");
		showSearch.put("categorySearch", "一级");

		Map<String, String> searchMap = new HashMap<>();
		searchMap.put("nameSearch", nameSearch);
		searchMap.put("categorySearch", categorySearch);
		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, searchMap);
		map.put("showSearch", showSearch);
		map.put("showSearchValue", searchMap);
		map.put("exactSearchFlag", exactSearchFlag);

		if (SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_DISEASE_INSPECTION_BLACKLIST)) {
			map.put("submitFlag", "1");
		}

		return new ModelAndView("icd/index", map);
	}

	public ReturnData getCategoryByName(String id, String name, String type) {
		// 获取一级
		String category = icdDiseaseDao.retrieveCategoryByName(name);
		if (category == null) {
			category = "";
		}

		// 查看该疾病本身是否为一级
		IcdDiseaseCategory icdDiseaseCategory = null;
		if ("1".equals(type)) {
			icdDiseaseCategory = icdDiseaseCategoryDao.retrieveObjectByDiseaseIdNew(id);
		} else {
			icdDiseaseCategory = icdDiseaseCategoryDao.retrieveObjectByDiseaseId(id);
		}

		Map<String, Object> data = new HashMap<>();
		data.put("category", category);
		if (icdDiseaseCategory != null) {
			data.put("categoryFlag", "1");
		}
		return ReturnUtil.success(data);
	}

	public ReturnData checkFormerName(String name) {
		Map<String, Object> param = new HashMap<>();
		param.put("formerName", name);
		param.put("disable", IcdDiseaseNameRecord.DISABLE_VALID);
		List<IcdDiseaseNameRecord> recordList = icdDiseaseNameRecordDao.retrieveList(param);
		if (recordList != null && recordList.size() > 0) {
			String returnName = "";
			for (IcdDiseaseNameRecord record : recordList) {
				returnName += record.getName() + "；";
			}

			Map<String, Object> data = new HashMap<>();
			data.put("formerName", returnName);
			return ReturnUtil.fail(ReturnCode.NAME_IS_A_FORMER_NAME, data);
		}
		return ReturnUtil.success();
	}

	public ModelAndView sexAgeList(Integer start, String keyword, String sexKey, String tabIdFlag,
			String countPerPageStr) {

		Map<String, Object> param = new HashMap<>();
		if (keyword != null && !keyword.isEmpty()) {
			param.put("keyword", keyword);
		}
		if (sexKey != null && !sexKey.isEmpty()) {
			param.put("sex", sexKey);
		}
		if (StringUtils.equals(tabIdFlag, "25_7")) {
			param.put("sexAgeFlag", BaseContants.FLAG_NO);
		} else {
			param.put("sexAgeFlag", BaseContants.FLAG_YES);
		}
		param.put("modified", "1");
		param.put("disable", BaseContants.DISABLE_VALID);
		int totalSize = icdDiseaseDao.retrieveDto2Size(param);

		Map<String, Integer> pageNo;
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			int countPerPage = Integer.parseInt(countPerPageStr);
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "", countPerPage);
			param.put("countPerPage", countPerPage);
		} else {
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "");
		}
		int endPage = pageNo.get("endPage");
		start = pageNo.get("start");
		int startIndex = pageNo.get("startIndex");

		List<IcdDiseaseDto> list = new ArrayList<>();

		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			list = icdDiseaseDao.retrieveDto2List(param);
		}
		
		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);

		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("keyword", "疾病名");
		map.put("showSearch", showSearch);
		
		map.put("ageArray", BusinessContants.ageArray);
		return new ModelAndView("icd/index", map);
	}

	public ReturnData setSex(String id, String sex, User user) {
		icdDiseaseDao.setSex(id, sex, user);

		// 校验该疾病的修改是否会出现同义词冲突
		String errMsg = checkSynonymy(id);
		if (!errMsg.isEmpty()) {
			ReturnCode rc = ReturnCode.ICD_DIEASE_SYNONYMY_SEX_AGE_CLASH;
			rc.setDesc(errMsg);
			return ReturnUtil.fail(rc);
		}

		return ReturnUtil.success();
	}

	private String checkSynonymy(String id) {
		IcdDisease icdDisease = icdDiseaseDao.retrieveObjectById(Long.parseLong(id));
		List<String> words = synonymyService.getWordListByWord(icdDisease.getName(), Synonymy.TYPE_ELEMENT,
				VocabConstant.ELEMENT_DISEASE);

		return checkSynonymySexAge(words);
	}

	public ReturnData setAge(String id, String age, Boolean flag, User user) {
		IcdDisease d = icdDiseaseDao.retrieveObjectById(Long.parseLong(id));

		if (flag) {
			// flag为true则添加该年龄段
			if (d.getAge() == null || d.getAge().indexOf(age) < 0) {
				age = (d.getAge() == null ? "" : d.getAge()) + age + ";";
			} else {
				age = d.getAge();
			}
		} else {
			// flag为false则去除该年龄段
			if (d.getAge() != null) {
				age = d.getAge().replace(age + ";", "");
			} else {
				age = "";
			}
		}

		// 校验该疾病的修改是否会出现同义词冲突
		String errMsg = checkSynonymy(id);
		if (!errMsg.isEmpty()) {
			ReturnCode rc = ReturnCode.ICD_DIEASE_SYNONYMY_SEX_AGE_CLASH;
			rc.setDesc(errMsg);

			return ReturnUtil.fail(rc);
		}
		icdDiseaseDao.setAge(id, age, user);
		return ReturnUtil.success();
	}

	public ReturnData submitSexAge(String ids, User user) {
		if (ids != null && !ids.isEmpty()) {
			if (ids.lastIndexOf(",") == ids.length() - 1) {
				ids = ids.substring(0, ids.length() - 1);
			}
			icdDiseaseDao.submitSexAge(ids, user);
		}
		return ReturnUtil.success();
	}

	public void exportSexAge(HttpServletResponse resp) throws Exception {
		RespHeaderUtil.setXlsxResp(resp, "疾病年龄性别");

		Workbook workbook = new XSSFWorkbook(); // 创建文档

		Map<String, Object> param = new HashMap<>();
		param.put("sexAgeFlag", BaseContants.FLAG_YES);
		List<IcdDisease> synonymList = icdDiseaseDao.retrieveList(param);

		Sheet sheet = workbook.createSheet(); // 创建Sheet
		// 循环写入数据
		Cell cell = null;
		int j = 0;
		for (int i = 0; i < synonymList.size(); i++) {
			IcdDisease icdDisease = synonymList.get(i);

			String age = icdDisease.getAge() == null ? "" : icdDisease.getAge();
			for (String subAge : age.split(";")) {
				Row row = sheet.createRow(j);
				cell = row.createCell(0);
				cell.setCellValue(icdDisease.getName());
				cell = row.createCell(1);
				if (icdDisease.getSex() == 1) {
					cell.setCellValue("男");
				} else if (icdDisease.getSex() == 2) {
					cell.setCellValue("女");
				}
				cell = row.createCell(2);
				cell.setCellValue(subAge);
				j++;
			}
		}

		OutputStream os = resp.getOutputStream();
		workbook.write(os);

		os.close();
		workbook.close();
	}

	public ReturnData setUrgentFlag(String id, String urgentFlag, User user) {
		icdDiseaseDao.setUrgentFlag(id, urgentFlag, user);
		return ReturnUtil.success();
	}

	public ReturnData setCheckCategory(String id, String checkCategory, User user) {
		icdDiseaseDao.setCheckCategory(id, checkCategory, user);
		return ReturnUtil.success();
	}

	/**
	 * 根据疾病同义词名称列表查询是否有性别年龄不同的数据
	 * 
	 * @param diseaseNames
	 * @return
	 */
	public String checkSynonymySexAge(List<String> diseaseNames) {

		if (diseaseNames.size() > 0) {
			List<String> diseases = icdDiseaseDao.retrieveListGroupBySexAge(diseaseNames);
			if (diseases.size() > 1) {
				StringBuilder desc = new StringBuilder();
				desc.append("疾病");
				for (String disease : diseases) {
					desc.append("【");
					desc.append(disease);
					desc.append("】");
				}
				desc.append("的性别年龄不一致，请校验");

				return desc.toString();
			}
		}
		return "";
	}

	/**
	 * 初始化疾病性别年龄区间概率
	 */
	public void initSexAge() {
		List<Map<String, Object>> allData = icdDiseaseDao.retrieveInitAgeSexData();
		List<IcdDiseaseDto> addRange = new ArrayList<>();
		for (Map<String, Object> data : allData) {
			String name = data.get("name") + "";
			String ageRange = data.get("age_range") + "";
			String cnt = data.get("cnt") + "";
			String[] ages = ageRange.split((char) 3 + "");
			String[] cnts = cnt.split((char) 3 + "");
			int sum = 0;
			for (int i = 0; i < cnts.length; i++) {
				sum += Integer.parseInt(cnts[i]);
			}
			IcdDiseaseDto value = new IcdDiseaseDto();
			value.setRange1(0.0);
			value.setRange2(0.0);
			value.setRange3(0.0);
			value.setRange4(0.0);
			value.setRange5(0.0);
			value.setRange6(0.0);
			value.setRange7(0.0);
			for (int i = 0; i < ages.length; i++) {
				switch (ages[i]) {
				case "0-0.34":
					value.setRange1(Double.parseDouble(cnts[i]) / sum);
					break;
				case "0.34-3":
					value.setRange2(Double.parseDouble(cnts[i]) / sum);
					break;
				case "3-10":
					value.setRange3(Double.parseDouble(cnts[i]) / sum);
					break;
				case "10-16":
					value.setRange4(Double.parseDouble(cnts[i]) / sum);
					break;
				case "16-45":
					value.setRange5(Double.parseDouble(cnts[i]) / sum);
					break;
				case "45-65":
					value.setRange6(Double.parseDouble(cnts[i]) / sum);
					break;
				case "65-93":
					value.setRange7(Double.parseDouble(cnts[i]) / sum);
					break;
				}
			}
			value.setName(name);
			addRange.add(value);
		}
		icdDiseaseDao.batchInsertAgeSex(addRange);
		// 更新disease_id
		icdDiseaseDao.updateDiseaseId();
	}

	public void diseaseExport(HttpServletResponse resp) throws Exception {
		// 获取已校验disease列表
		Map<String, Object> param = new HashMap<>();
		param.put("disable", BaseContants.DISABLE_VALID);

		List<IcdDiseaseDto> diseaseList = icdDiseaseDao.retrieveDtoList(param);

		LOGGER.info("diseaseExport get list success!size=" + diseaseList.size());

		// 设置respons的头信息
		RespHeaderUtil.setXlsxResp(resp, "disease");

		// 创建文档
		XSSFWorkbook workbook = new XSSFWorkbook();
		Sheet sheet = workbook.createSheet("disease"); // 创建Sheet

		// 循环写入数据
		IcdDiseaseDto disease = null;
		Row row = null;
		for (int i = 0; i < diseaseList.size(); i++) {
			disease = diseaseList.get(i);
			row = sheet.createRow(i);
			List<String> cellValues = new ArrayList<>();
			cellValues.add(disease.getName());
			cellValues.add(disease.getCategory() == null ? "" : disease.getCategory());
			cellValues.add(disease.getUrgentFlag() == null ? "" : disease.getUrgentFlag() + "");
			cellValues.add(disease.getCheckCategory() == null ? "" : disease.getCheckCategory() + "");
			addCell(row, cellValues);
		}
		LOGGER.info("diseaseExport create excel success!");

		OutputStream os = resp.getOutputStream();
		workbook.write(os);
		workbook.close();

		os.close();
	}

	private void addCell(Row row, List<String> cellValues) {
		if (cellValues.size() > 0) {
			Cell cell = null;
			for (int i = 0; i < cellValues.size(); i++) {
				String cellValue = cellValues.get(i);
				cell = row.createCell(i);
				cell.setCellValue(cellValue);
			}
		}
	}

	private String getCellNum(Row row, int num) {
		Cell cell = row.getCell(num);
		String index = "";
		if (cell != null) {
			cell.setCellType(Cell.CELL_TYPE_STRING);
			index = cell.getStringCellValue().trim();
		}
		return index;
	}

	public ReturnData diseaseImport(MultipartFile file, User user) throws Exception {

		InputStream inputStream = null;
		Workbook workbook = null;

		try {
			// 获取文件流，解析文件
			inputStream = file.getInputStream();

			workbook = new XSSFWorkbook(inputStream);
			Sheet sheet = workbook.getSheetAt(0);
			List<Map<String, String>> updateList = new ArrayList<>();

			for (Row row : sheet) {
				String diseaseName = getCellNum(row, 0);
				String urgentFlag = getCellNum(row, 2);
				String checkCategory = getCellNum(row, 3);
				if (!StringUtils.equals(urgentFlag, "0") && !StringUtils.equals(urgentFlag, "1")) {
					ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
					rc.setDesc("是否紧急只有0,1枚举值");
					return ReturnUtil.fail(rc);
				}
				if (!StringUtils.equals(checkCategory, "0") && !StringUtils.equals(checkCategory, "1")) {
					ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
					rc.setDesc("是否化验检查只有0,1枚举值");
					return ReturnUtil.fail(rc);
				}
				Map<String, String> updateMap = new HashMap<>();
				updateMap.put("diseaseName", diseaseName);
				updateMap.put("urgentFlag", urgentFlag);
				updateMap.put("checkCategory", checkCategory);
				updateList.add(updateMap);
			}
			for (Map<String, String> update : updateList) {
				icdDiseaseDao.updateUrgentCheckCategory(update);
			}

		} catch (Exception e) {
			throw e;
		} finally {
			workbook.close();
			inputStream.close();
		}
		return ReturnUtil.success();
	}
}
